#include "scene.h"
#include <cmath>
#include <GL/gl.h>
#include <iostream>

Scene::Scene(){
    idObjects = 0;
    octreeDepth = 3;
}

Scene::~Scene(){
    unsigned int size = objects.size();
    for(unsigned int i = 0; i < size; i++){
        Object *obj = objects.back();
        objects.pop_back();
        delete obj;
    }

    size = octrees.size();
    for(unsigned int i = 0; i < size; i++){
        Octree *oct = octrees.back();
        octrees.pop_back();
        delete oct;
    }
}

void Scene::addObject(Object *_o){
    objects.push_back(_o);
}

Object *Scene::getObject(unsigned int _i) const{
    return objects[_i];
}

unsigned int Scene::getObjectsSize() const{
    return objects.size();
}

void Scene::deleteObject(Object *_o){
    int size = objects.size();
    for (int i = size; i > 0; i--){
        if ( objects.at(i - 1) == _o ){
            objects.erase(objects.begin() + i - 1);
            if(!octrees.empty()){
                Octree *octree = octrees.at(i - 1);
                octrees.erase(octrees.begin() + i - 1);
                delete octree;
            }
        }
    }
}

int Scene::nextObjectsID(){
    return idObjects++;
}

void Scene::setNextObjectsID(int _id){
    idObjects = _id + 1;
}

void Scene::setOctrees(std::vector<Octree *> _octrees){
    octrees = _octrees;
}

Octree *Scene::getOctree(unsigned int _i) const{
    return octrees[_i];
}

Octree *Scene::getOctree(Object *_obj) const{
    for(unsigned int i = 0; i < octrees.size(); i++){
        if(octrees.at(i)->getObject() == _obj)
            return octrees[i];
    }
    std::cout <<"Não foi achada nenhuma octree" <<std::endl;
    return NULL;
}

unsigned int Scene::getOctreesSize() const{
    return octrees.size();
}

void Scene::changeDepth(int _d){
    octreeDepth = _d;
}

Octree *Scene::addOctreeOf(Object *_obj){
    //deleta antes se existir a octree
    for(unsigned int i = 0; i < octrees.size(); i++){
        Octree *octree = octrees.at(i);
        if(octree->getObject() == _obj){
            octrees.erase(octrees.begin() + i);
            delete octree;
            break;
        }
    }
    Octree *octree = new Octree(_obj, octreeDepth);
    octrees.push_back(octree);
    return octree;
}

void Scene::octree(bool _b){
    if(_b){
        for(unsigned int i = 0; i < objects.size(); i++){
            octrees.push_back(new Octree(objects.at(i), octreeDepth));
        }

    }else{
        unsigned int size = octrees.size();
        for(unsigned int i = 0; i < size; i++){
            Octree *oct = octrees.back();
            octrees.pop_back();
            delete oct;
        }
    }
}

void Scene::draw(bool _showObjects, bool _showWireframeObjects, bool _showWireframeOctree, bool _showBorderOctree){
//    std::cout <<"Existem " << objects.size() << " objectos" << std::endl;
    if(_showObjects){
        Object *obj;
        for(unsigned int i = 0; i < objects.size(); i++){
//            std::cout <<"\tDesenhando objeto " << objects.at(i)->getId() << std::endl;
            obj = objects.at(i);
            obj->draw(_showWireframeObjects);
        }
    }

    Octree *oct;
//    std::cout <<"Existem " << octrees.size() << " octrees" << std::endl;
    for(unsigned int i = 0; i < octrees.size(); i++){
//        std::cout <<"\tDesenhando octree " << octrees.at(i)->getObject()->getId() << std::endl;
        oct = octrees.at(i);
        oct->draw(_showWireframeOctree, _showBorderOctree);
    }
}
